package com.example.util;

import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 本文来演示:JobRecommend的协同类
 *
 * @author 赵建云
 * @create 2023/10/16
 */
public class JobCollaborativeFiltering {
    private JobRecommendUtils jobRecommendUtils;
    public JobCollaborativeFiltering(JobRecommendUtils jobRecommendUtils) {
        this.jobRecommendUtils = jobRecommendUtils;
    }
    public float calculateSimilarity(Map<Integer, Float> userRatings, Map<Integer, Float> otherUserRatings) {
        float numerator = 0;
        float denominator1 = 0;
        float denominator2 = 0;

        for (Map.Entry<Integer, Float> entry : userRatings.entrySet()) {
            Integer productId = entry.getKey();
            Float rating = entry.getValue();

            if (otherUserRatings.containsKey(productId)) {
                Float otherUserRating = otherUserRatings.get(productId);

                numerator += rating * otherUserRating;
                denominator1 += rating * rating;
                denominator2 += otherUserRating * otherUserRating;
            }
        }

        float similarity = numerator / (float) (Math.sqrt(denominator1) * Math.sqrt(denominator2));
        return similarity;
    }

    public float calculatePredictedRating(Integer userId, Integer productId, Map<Integer, Float> similarities) {
        float numerator = 0;
        float denominator = 0;

        for (Map.Entry<Integer, Float> entry : similarities.entrySet()) {
            Integer otherUserId = entry.getKey();
            Float similarity = entry.getValue();

            Float rating = jobRecommendUtils.getClick(otherUserId, productId);

            if (rating != null) {
                numerator += similarity * rating;
                denominator += Math.abs(similarity);
            }
        }

        float predictedRating = numerator / denominator;
        return predictedRating;
    }

    public List<Integer> getRecommendedProducts(Integer userId) {
        Map<Integer, Float> userRatings = jobRecommendUtils.getClicks(userId);
        Set<Integer> productIds = jobRecommendUtils.getProductIds();
        Map<Integer, Float> similarities = new HashMap<>();
        for (Integer otherUserId : jobRecommendUtils.getJsIds()) {
            if (!otherUserId.equals(userId)) {
                Map<Integer, Float> otherUserRatings = jobRecommendUtils.getClicks(otherUserId);
                float similarity = calculateSimilarity(userRatings, otherUserRatings);
                similarities.put(otherUserId, similarity);
            }
        }

        List<Integer> recommendedProducts = new ArrayList<>();
        for (Integer productId : productIds) {
            Float rating = jobRecommendUtils.getClick(userId, productId);
            if (rating == null) {
                float predictedRating = calculatePredictedRating(userId, productId, similarities);
                if (predictedRating >= 4.0) {
                    recommendedProducts.add(productId);
                }
            }
        }
        return recommendedProducts;
    }
}

